import { useLoadRightMenu, type useLoadRightMenuResult } from './MenuModelLoad'
import RightMenu from '@/components/RightMenu.vue';
import { useLoadWidget } from '@/hook/PopupMenuComponent'

export class useRightMenu {

    /**
     * 需要右击菜单的元素
     */
    rightMenuBoundEvent: HTMLElement | null;
    
    /**
     * 加载右击菜单
     */
    useLoadMenu: useLoadRightMenuResult | null = null;

    /**
     * 右击菜单的标识
     */
    RIGHTMENUNAME_PREFIX: String = "RightMenu"
    /**
     * 菜单名称
     */
    RightMenuName: string = ""
    /**
     * 当前正在显示的元素
     */
    CurrentShowElement: HTMLElement[] = new Array(0);
    /**
     * 当前保存的数据
     */
    CurrentMerData: object = {};
    /**
     * 返回的数据就是右击菜单打开组件的数据
     */
    SaveRightMenuFn: Function | null = null;
    /**
     * 简单模式下监听点击事件
     */
    ChangeRightMenuHandle: Function | null = null;

    /**
     * 绑定右键菜单的元素
     * @param rightMenuBound 绑定右键的元素
     * @param menuName 菜单的名称
     * @returns 
     */
    constructor(rightMenuBound?: HTMLElement, menuName?: string) {
        this.rightMenuBoundEvent = rightMenuBound ? rightMenuBound : null

        this.RightMenuName = menuName ? menuName : ''

        this.useLoadMenu = useLoadRightMenu({
            component: RightMenu
        })

        return this;
    }

    /**
     * 添加右击事件
     */
    addRightMenuEvent(fn?: Function) {

        fn && (this.ChangeRightMenuHandle = fn);

        this.rightMenuBoundEvent?.addEventListener("contextmenu", this.ContextMenuHandle.bind(this))
        window.addEventListener("click", this.ClickMenuHandle.bind(this))
    }
    /**
     * 修改简单模式下的监听方法
     * @param fn 
     */
    setChangeRightMenuHandle(fn: Function | null) {
        this.ChangeRightMenuHandle = fn
    }
    /**
     * 菜单点击时触发的方法
     * @param e 
     */
    ContextMenuHandle(e: any) {
        e.preventDefault();

        let { pageX, pageY } = e;

        // <--------此变量暂时未用上---——-->
        this.CurrentMerData = this.SaveRightMenuFn instanceof Function && this.SaveRightMenuFn();

        /**
         * 加载右击菜单
         */
        this.useLoadMenu?.LoadingRightMenu({
            pageX,
            pageY,
            params: {
                ChangeRightMenuHandle: this.ChangeRightMenuHandle
            },
            name: this.RightMenuName
        })

    }

    /**
     * 点击事件，鼠标点击任意处，关闭菜单
     * @param e 
     */
    ClickMenuHandle(e: any) {
        if (e.preventDefault) {
            e.preventDefault();
            let className = typeof e.target.className == "string" ? e.target.className : '';
            let flag = className.includes(this.RIGHTMENUNAME_PREFIX)
            !flag && this.useLoadMenu?.unLoadingRightMenu()
        }
    }
    /**
     * 销毁事件
     */
    destroy() {
        this.rightMenuBoundEvent?.removeEventListener("contextmenu", this.ContextMenuHandle)
        window.removeEventListener("click", this.ClickMenuHandle)
    }

    // -------------------------上面为绑定事件，就是使用者事件，下面为开发者使用的事件-------------


    /**
     * 生成菜单元素
     * @param data 
     */
    createRightMenuElement = (data: any, className?: string | null, CallBack?: Function) => {
        let self = this;
        let ul = document.createElement("ul")
        ul.classList.add("RightMenu_List")
        className && ul.classList.add(`RightMenu_${className}`)
        className && ul.classList.add(`RightMenu_children`)
        data.forEach((item: any, index: number) => {
            let li = document.createElement("li")
            let span = document.createElement("span")
            li.classList.add("RightMenu_li")
            span.classList.add("RightMenu_span")

            span.innerText = item.label;

            let children = null;
            let i;
            if (item.children) {
                children = self.createRightMenuElement(item.children, item.label, CallBack)
                i = document.createElement("i")
                i.innerHTML = "›"
                i.classList.add("RightMenu_i")
            }
            li.appendChild(span)

            self.MenuChildrenAddHandle(item, li, CallBack)

            children && i && li.appendChild(i)
            children && li.appendChild(children)

            ul.appendChild(li)
        })
        return ul;
    }

    /**
     * 为菜单的每一项注册相应的事件
     */
    MenuChildrenAddHandle(item: any, element: HTMLElement, CallBack?: Function) {
        let self = this;
        let type = item.children ? 0 : item.fn ? 1 : 2;

        switch (type) {
            case 0:
                // 如果当前元素有子节点，则添加 打开/隐藏事件
                element.addEventListener("click", (event: any) => {
                    self.MenuClickShowChildren(element, item)
                }, true)
                break;
            case 1:
                // 如果当前元素有需要执行的方法，则直接抛出，或默认调用onLoad方法名
                element.addEventListener("click", (event: any) => {
                    // 关闭除自身外所有展开的节点
                    self.MenuHideAllChildren(element, self.CurrentShowElement)
                    if (CallBack) {
                        let { onLoad } = item.fn();
                        CallBack(event, element, { type: "fn", item: item }, onLoad)
                    } else if (item.fn instanceof Function) {
                        let { onLoad } = item.fn();
                        onLoad instanceof Function ? onLoad() : console.warn("无onLoad方法");
                    }
                }, true)
                break;
            case 2:
                // 如果当前元素有component属性，则证明用户想打开一个组件
                const { initialLoadWidget } = useLoadWidget(item.component);
                element.addEventListener("click", (event: any) => {
                    // 关闭除自身外所有展开的节点
                    self.MenuHideAllChildren(element, self.CurrentShowElement)
                    if (CallBack) {
                        CallBack(event, element, { type: "component", item: item })
                    } else {
                        initialLoadWidget({ ...self.CurrentMerData })
                    }
                })
                break;
            default:
                break;
        }
    }
    /**
     * 菜单点击显示子节点
     */
    MenuClickShowChildren(element: HTMLElement, row: any) {

        let ele = element.getElementsByClassName("RightMenu_children")[0] as HTMLElement;

        // 将之前显示的元素隐藏
        this.MenuHideAllChildren(ele, this.CurrentShowElement)

        ele && (ele.style.display = "block");

        // 添加当前点击过的元素
        this.CurrentShowElement?.push(ele);

    }
    /**
     * 
     * @param o1 新元素
     * @param o2 旧元素
     * @returns 
     */
    MenuHideAllChildren(o1: HTMLElement | null, o2: HTMLElement[]) {
        if (!o2) return false;

        o2.forEach((element: HTMLElement, index: number) => {
            if (!element.contains(o1)) {
                let all = element.getElementsByClassName("RightMenu_children");

                // 找到当前元素下面所有的ul元素，隐藏
                all && Array.from(all).forEach((item: Element) => {
                    (item as HTMLElement).style.display = "none";
                })

                // 将当前的元素隐藏
                element.style.display = "none"
                // 将无用的元素去掉
                o2.splice(0, index + 1);
                return true;
            }
        })

        return true;
    }

}